package com.totem.customer.serivce.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.totem.base.constants.CommonConstants;
import com.totem.base.constants.ErrorCode;
import com.totem.base.enums.*;
import com.totem.base.exception.BaseException;
import com.totem.base.util.DateUtils;
import com.totem.customer.mapper.*;
import com.totem.customer.model.TCustomers;
import com.totem.customer.model.TInvite;
import com.totem.customer.model.TMembers;
import com.totem.customer.serivce.IMemberCommonService;
import com.totem.customer.serivce.ITMemberService;
import com.totem.customer.vo.InvitePathVO;
import com.totem.customer.vo.MemberVO;
import com.totem.customer.vo.SubscribeIncentiveVO;
import com.totem.customer.vo.TeamIncentiveVO;
import com.totem.order.mapper.TWalletJournalMapper;
import com.totem.order.mapper.TWalletMapper;
import com.totem.order.model.TOrders;
import com.totem.order.model.TWalletJournal;
import com.totem.order.model.TWallets;
import com.totem.order.service.ITWalletJournalService;
import com.totem.order.service.ITWalletService;
import com.totem.product.model.TSubscribe;
import com.totem.startup.InitialGlobalConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
public class TMemberCommonServiceImpl implements IMemberCommonService {
    @Autowired
    private TCustomerMapper tCustomerMapper;
    @Autowired
    private TInviteMapper tInviteMapper;
    @Autowired
    private TMemberMapper tMemberMapper;
    @Autowired
    private ITMemberService itMemberService;
    @Autowired
    private TWalletMapper tWalletMapper;
    @Autowired
    private ITWalletService itWalletService;
    @Autowired
    private TWalletJournalMapper tWalletJournalMapper;
    @Autowired
    private ITWalletJournalService itWalletJournalService;

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void calDistributiveAward(TOrders tOrder, TWalletJournal journal, TSubscribe tSubscribe) {
        Long customerId = journal.getCustomerId();
        LambdaQueryWrapper<TInvite> inviteQuery = new LambdaQueryWrapper<>();
        inviteQuery.eq(TInvite::getInviteeId, customerId);
        TInvite tInvite = tInviteMapper.selectOne(inviteQuery);
        if(tInvite==null){
            log.warn("客户[{}]未受到邀请", customerId);
            return;
        }

        String invitePath = tInvite.getPath();
        Long inviterId = tInvite.getInviterId();
        List<String> pathList = Arrays.asList(invitePath.split(","));
        // 注意,父级顺序是从左到右的,即第一个元素是直接推荐人
        List<Long> parentIds = pathList.stream().map(Long::valueOf).toList();
        // log.debug("invitePath: {}, {}", invitePath, pathList);

        LambdaQueryWrapper<TMembers> memberQuery = new LambdaQueryWrapper<>();
        memberQuery.in(TMembers::getCustomerId, parentIds);
        List<TMembers> memberList = tMemberMapper.selectList(memberQuery);

        calAward(parentIds, journal, memberList, tSubscribe);
    }

    private void calAward(List<Long> walkInviterIds, TWalletJournal journal, List<TMembers> memberList, TSubscribe tSubscribe){
        Long orderId = journal.getOrderId();
        BigDecimal investAmt = journal.getAmount();
        Long directParentId = walkInviterIds.get(0);

        Map<Integer, BigDecimal> inviteAwardRule = InitialGlobalConfig.INVITE_AWARD_RULE;
        Map<Integer, TeamIncentiveVO> teamMotivation = InitialGlobalConfig.TEAM_MOTIVATION_RULE;
        Map<String, SubscribeIncentiveVO> specSubscribe = InitialGlobalConfig.SPEC_SUBSCRIBE_RULE;

        Map<Long, TMembers> membersMap = memberList.stream().collect(Collectors.toMap(TMembers::getCustomerId, Function.identity()));

        // 计算邀请奖励
        Map<Long, BigDecimal> inviteAward = new HashMap<>();
        for(int i=0; i<inviteAwardRule.size() && i<walkInviterIds.size(); i++){
            Long parentId = walkInviterIds.get(i);
            BigDecimal awardAmt = inviteAwardRule.get(i).multiply(investAmt).setScale(CommonConstants.DEFAULT_SCALE, RoundingMode.HALF_UP);
            inviteAward.put(parentId, awardAmt);
        }

        // 计算团队奖励
        Map<Long, BigDecimal> teamAward = new HashMap<>();
        int maxLevel = 0;
        for(int i=0; i<walkInviterIds.size(); i++){
            // 上一个邀请人的会员等级已经达到最大,奖励已发完
            if(maxLevel>= teamMotivation.size()){
                break;
            }
            Long parentId = walkInviterIds.get(i);
            TMembers tMembers = membersMap.get(parentId);
            // 计算奖励时以待遇等级为准
            int parentLevel = tMembers.getEnjoyLevel();
            // 子树中会员的最大等级不比当前会员的低,则当前会员无法再分到奖励
            if(maxLevel>=parentLevel){
                continue;
            }
            // 当前会员的等级大于子树中会员的最大等级,还有奖励可分
            TeamIncentiveVO parentTeamIncentive = teamMotivation.get(parentLevel);
            BigDecimal distributive = parentTeamIncentive.getIncome();
            // 计算可分配收益率
            if(maxLevel>0){
                TeamIncentiveVO maxTeamIncentive = teamMotivation.get(maxLevel);
                distributive = distributive.subtract(maxTeamIncentive.getIncome());
            }
            // 可分配收益率计算完, 更新当前会员树的最大会员等级
            maxLevel = parentLevel;
            BigDecimal awardAmt = distributive.multiply(investAmt).setScale(CommonConstants.DEFAULT_SCALE, RoundingMode.HALF_UP);
            teamAward.put(parentId, awardAmt);
        }
        // 计算特殊认购奖励
        Map<Long, BigDecimal> subscribeAward = new HashMap<>();
        if(!SubscribeLevelEnum.isNormal(tSubscribe.getSubscribeLevel())){
            SubscribeIncentiveVO specIncentive = specSubscribe.get(tSubscribe.getSubscribeName());
            BigDecimal awardAmt = specIncentive.getInviteAwardRate().multiply(investAmt).setScale(CommonConstants.DEFAULT_SCALE, RoundingMode.HALF_UP);
            subscribeAward.put(directParentId, awardAmt);
        }

        LambdaQueryWrapper<TWallets> walletQuery = new LambdaQueryWrapper<>();
        walletQuery.in(TWallets::getCustomerId, walkInviterIds);
        List<TWallets> walletList = tWalletMapper.selectList(walletQuery);
        Map<Long, TWallets> walletsMap = walletList.stream().collect(Collectors.toMap(TWallets::getCustomerId, Function.identity()));

        String currency = journal.getCurrency();
        List<TWallets> updateWalletList = walletList.stream().map(w->{
            TWallets update = TWallets.builder()
                    .customerId(w.getCustomerId())
                    .build();

            BigDecimal custInviteAward = inviteAward.get(w.getCustomerId());
            custInviteAward = custInviteAward==null?BigDecimal.ZERO:custInviteAward;

            BigDecimal custTeamAward = teamAward.get(w.getCustomerId());
            custTeamAward = custTeamAward==null?BigDecimal.ZERO:custTeamAward;

            BigDecimal custSubscribeAward =subscribeAward.get(w.getCustomerId());
            custSubscribeAward = custSubscribeAward==null?BigDecimal.ZERO:custSubscribeAward;

            BigDecimal award = custInviteAward.add(custTeamAward).add(custSubscribeAward);

            if(CurrencyEnum.isUSDO(currency)){
                BigDecimal bal = w.getUsdo().add(award);
                update.setUsdo(bal);
            }
            if(CurrencyEnum.isUSDT(currency)){
                BigDecimal bal = w.getUsdt().add(award);
                update.setUsdt(bal);
            }
            return update;
        }).toList();

        //tWalletMapper.batchUpdateById(updateWalletList);
        itWalletService.updateBatchById(updateWalletList);

        List<TMembers> memberUpdateList = memberList.stream().map(m->{
            TMembers updateMember = TMembers.builder()
                    .customerId(m.getCustomerId())
                    .build();

            BigDecimal custInviteAward = inviteAward.get(m.getCustomerId());
            custInviteAward = custInviteAward==null?BigDecimal.ZERO:custInviteAward;

            BigDecimal custTeamAward = teamAward.get(m.getCustomerId());
            custTeamAward = custTeamAward==null?BigDecimal.ZERO:custTeamAward;

            BigDecimal custSubscribeAward =subscribeAward.get(m.getCustomerId());
            custSubscribeAward = custSubscribeAward==null?BigDecimal.ZERO:custSubscribeAward;

            updateMember.setAward(m.getAward().add(custInviteAward).add(custSubscribeAward));
            updateMember.setTeamAward(m.getTeamAward().add(custTeamAward));

            return updateMember;
        }).toList();

        itMemberService.updateBatchById(memberUpdateList);

        List<TWalletJournal> inviteAwardJournalList = inviteAward.entrySet().stream().map(ia->{
            TWallets wallet = walletsMap.get(ia.getKey());
            BigDecimal beforeBal = null;
            BigDecimal amt = inviteAward.get(ia.getKey());
            if(CurrencyEnum.isUSDO(currency)){
                beforeBal = wallet.getUsdo();
            }
            if(CurrencyEnum.isUSDT(currency)){
                beforeBal = wallet.getUsdt();
            }
            BigDecimal afterBal = beforeBal.add(amt);
            TWalletJournal tWalletJournal = TWalletJournal.builder()
                    .customerId(wallet.getCustomerId())
                    .orderId(orderId)
                    .journalType(JournalTypeEnum.INVITE_AWARD.getCode())
                    .beforeBalance(beforeBal)
                    .amount(amt)
                    .afterBalance(afterBal)
                    .charges(BigDecimal.ZERO)
                    .direction(DirectionEnum.DEBIT.getCode())
                    .journalState(JournalStateEnum.FINISHED.getCode())
                    .currency(currency)
                    .remark("支付认购包后根据邀请关系奖励")
                    .build();
            return tWalletJournal;
        }).toList();

        itWalletJournalService.saveBatch(inviteAwardJournalList);
    }

    @Override
    public void onInvite(Long inviterId) {
        calMemberLevel(inviterId);
    }

    // 当支付认购包时计算会员等级
    // 为邀请路径上的所有推广人增加团队投入
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void onSubscribePayment(TWalletJournal journal, List<TMembers> inviterMemberList, List<Long> parentIdList) {
        Long customerId = journal.getCustomerId();
        BigDecimal invest = journal.getAmount();

        // 为邀请路径上的所有推广人增加团队投入
        List<TMembers> inviterUpdateList = inviterMemberList.stream().map(inviterMember->{
            TMembers inviterUpdate = TMembers.builder()
                    .customerId(inviterMember.getCustomerId())
                    .teamInvest(inviterMember.getTeamInvest().add(invest))
                    .build();
            return inviterUpdate;
        }).toList();
        itMemberService.updateBatchById(inviterUpdateList);

        // 为当前投入的客户计算会员等级
        calMemberLevel(customerId);

        // 为当前投入的客户的上级推广人计算会员等级
        if(!CollectionUtils.isEmpty(parentIdList)) {
            parentIdList = new ArrayList<>(parentIdList);
            parentIdList.remove(customerId);
            if(!CollectionUtils.isEmpty(parentIdList)) {
                parentIdList.forEach(this::calMemberLevel);
            }
        }
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    @Override
    public void calMemberLevel(Long customerId) {
        TMembers member = tMemberMapper.selectById(customerId);

        int memberLevel = member.getMemberLevel();
        int newLevel = matchMemberLevel(member);

        // 满足考核要求,只能升
        if(newLevel>memberLevel){
            adjustMemberLevel(newLevel, member);
        }
    }

    public void updateInvite(Long customerId, Long newInviterId, Integer newMemberLevel, List<TInvite> teamInviteList) {
        List<Long> teamMemberIdList = teamInviteList.stream().map(TInvite::getInviteeId).toList();
        Map<Long, TInvite> teamMemberMap = teamInviteList.stream().collect(Collectors.toMap(TInvite::getInviteeId, Function.identity()));

        TMembers member = tMemberMapper.selectById(customerId);
        if(member==null){
            throw new BaseException(ErrorCode.NOT_EXIST_MEMBER);
        }
        Integer custMemberLevel = member.getMemberLevel();
        Integer custEnjoyLevel = member.getEnjoyLevel();
        // 父级的团队业绩,旧父级需要扣掉该业绩,新父级需要新增该业绩
        BigDecimal parentTeamInvest = member.getInvest().add(member.getTeamInvest());
        TMembers updateMember = TMembers.builder()
                .customerId(customerId)
                .build();

        // 团队成员的最高会员级别,分别为更新前(旧)和更新后的(新)
        Integer oldMemberMaxLevel = custMemberLevel;
        Integer newMemberMaxLevel = null;
        if(newMemberLevel!=null) {
            if (!Objects.equals(custMemberLevel, newMemberLevel)) {
                updateMember.setMemberLevel(newMemberLevel);
                // 如果新的会员等级高于待遇等级,则修改待遇等级,否则待遇等级不变
                if(newMemberLevel>custEnjoyLevel){
                    updateMember.setEnjoyLevel(newMemberLevel);
                }
                tMemberMapper.updateById(updateMember);
            }
        }
        if(!CollectionUtils.isEmpty(teamMemberIdList)) {
            Integer teamMemberMaxLevel = maxMemberLevel(teamMemberIdList);
            // 如果团队成员的最高级别比当前客户的最高级别高,则使用团队成员的最高级别作为旧的最高级别
            if(teamMemberMaxLevel>oldMemberMaxLevel){
                oldMemberMaxLevel = teamMemberMaxLevel;
            }
            if(newMemberLevel!=null){
                if(teamMemberMaxLevel>newMemberLevel) {
                    newMemberMaxLevel = teamMemberMaxLevel;
                }else{
                    newMemberMaxLevel = newMemberLevel;
                }
            }else{
                newMemberMaxLevel = teamMemberMaxLevel;
            }
        }

        // 重构path
        if(newInviterId!=null) {
            LambdaQueryWrapper<TInvite> inviteQuery = new LambdaQueryWrapper<>();
            inviteQuery.eq(TInvite::getInviteeId, customerId);
            TInvite oldInvite = tInviteMapper.selectOne(inviteQuery);
            if(oldInvite!=null){
                Long oldInviterId = oldInvite.getInviterId();
                if(!Objects.equals(oldInviterId, newInviterId)){
                    tInviteMapper.deleteById(oldInvite.getId());
                    // 后台管理界面变更邀请人时,不计算会员数据(因为不是新会员),而是单独处理
                    String inviteRemark = oldInvite.getRemark()==null?"":(oldInvite.getRemark()+";");
                    String ctStr = DateUtils.formatDate(oldInvite.getCreateTime(), CommonConstants.DEFAULT_DATETIME_FORMAT);
                    inviteRemark=inviteRemark+"Inviter-"+oldInviterId+",CT-"+ctStr;
                    TInvite newInvite = execInvite(newInviterId, customerId, false, inviteRemark);
                    // todo 上级会员的会员数据全部需要重置,包括新旧父级
                    resetPathMemberData(oldInvite, newInvite, parentTeamInvest, oldMemberMaxLevel, newMemberMaxLevel);

                    // 下级团队成员的path全部需要重构
                    if(!CollectionUtils.isEmpty(teamMemberIdList)) {
                        teamMemberIdList.forEach(memberId->{
                            String newInvitePath = buildPath(memberId);
                            TInvite memberInvite = teamMemberMap.get(memberId);
                            if(memberInvite!=null) {
                                log.debug("邀请关系变更:之前:{},之后:{}", memberInvite.getPath(), newInvitePath);
                                LambdaUpdateWrapper<TInvite> updateTeamQuery = new LambdaUpdateWrapper<>();
                                updateTeamQuery.set(TInvite::getPath, newInvitePath);
                                updateTeamQuery.eq(TInvite::getInviteeId, memberId);
                                updateTeamQuery.eq(TInvite::getInviterId, memberInvite.getInviterId());
                                tInviteMapper.update(updateTeamQuery);
                            }
                        });
                    }
                }
            }
        }
    }

    public Integer maxMemberLevel(List<Long> customerIdList){
        Integer memberMaxLevel = 0;
        QueryWrapper<TMembers> teamMemQuery = new QueryWrapper<>();
        teamMemQuery.select("max(member_level) as memberLevel");
        teamMemQuery.in("customer_id", customerIdList);
        List<Map<String, Object>> maxMemberLevelMapList = tMemberMapper.selectMaps(teamMemQuery);
        if(!CollectionUtils.isEmpty(maxMemberLevelMapList)){
            Map<String, Object> maxMemberLevelMap = maxMemberLevelMapList.get(0);
            Object memberMaxLevelObj = maxMemberLevelMap.get("memberLevel");
            memberMaxLevel = (Integer)memberMaxLevelObj;
        }
        return memberMaxLevel;
    }

    public TInvite execInvite(Long inviterId, Long inviteeId, boolean calMember, String remark){
        String invitePath = buildPath(inviterId);

        TInvite tInvite = TInvite.builder()
                .inviterId(inviterId)
                .inviteeId(inviteeId)
                .path(invitePath)
                .build();

        if(StringUtils.isNotBlank(remark)){
            tInvite.setRemark(remark);
        }
        tInviteMapper.insert(tInvite);

        final Long finalInviterId = inviterId;

        if(calMember) {
            tMemberMapper.incrV0Count(inviterId);
            // 计算推广人的会员等级
            onInvite(finalInviterId);
        }
        return tInvite;
    }

    @Override
    public String buildPath(Long customerId){
        List<InvitePathVO> invitePathVOList = tInviteMapper.findInvitePathById(customerId);
        String invitePath = "";
        if(!CollectionUtils.isEmpty(invitePathVOList)) {
            invitePath = invitePathVOList.stream().map(ip->ip.getInviterId().toString()).collect(Collectors.joining(","));
            invitePath = customerId+","+invitePath;
        }else{
            invitePath = customerId.toString();
        }
        return invitePath;
    }

    // 检查当前业绩所匹配的会员等级
    public Integer matchMemberLevel(TMembers member){
        int matchInviteCountLevel = matchInviteCountLevel(member);
        int matchPersonalInvestLevel = matchPersonalAppraisalLevel(member);
        int matchTeamInvestLevel = matchTeamAppraisalLevel(member);
        int memberLevel = Math.min(matchTeamInvestLevel, matchPersonalInvestLevel);
        memberLevel = Math.min(memberLevel, matchInviteCountLevel);
        return memberLevel;
    }

    public Integer matchInviteCountLevel(TMembers member){
        Map<Integer, TeamIncentiveVO> teamMotivation = InitialGlobalConfig.TEAM_MOTIVATION_RULE;
        int v0Count = member.getV0Count();
        int v1Count = member.getV1Count();
        int v2Count = member.getV2Count();
        int v3Count = member.getV3Count();
        int v4Count = member.getV4Count();
        int v5Count = member.getV5Count();

        if(v5Count>=teamMotivation.get(6).getTeamCount()){
            return 6;
        }else if((v4Count+v5Count)>=teamMotivation.get(5).getTeamCount()){
            return 5;
        }else if((v3Count+v4Count+v5Count)>=teamMotivation.get(4).getTeamCount()){
            return 4;
        }else if((v2Count+v3Count+v4Count+v5Count)>=teamMotivation.get(3).getTeamCount()){
            return 3;
        }else if((v1Count+v2Count+v3Count+v4Count+v5Count)>=teamMotivation.get(2).getTeamCount()){
            return 2;
        }else if((v0Count+v1Count+v2Count+v3Count+v4Count+v5Count)>=teamMotivation.get(1).getTeamCount()){
            return 1;
        }else{
            return 0;
        }
    }

    public Integer matchPersonalAppraisalLevel(TMembers member){
        Map<Integer, TeamIncentiveVO> teamMotivation = InitialGlobalConfig.TEAM_MOTIVATION_RULE;

        int level = 0;
        if(member.getInvest()==null){
            return level;
        }
        for(int i=teamMotivation.size(); i>0; i--){
            TeamIncentiveVO incentiveVO = teamMotivation.get(i);
            if(incentiveVO.getPersonalAppraisal().compareTo(member.getInvest())<=0){
                level = i;
                break;
            }
        }
        return level;
    }

    public Integer matchTeamAppraisalLevel(TMembers member){
        Map<Integer, TeamIncentiveVO> teamMotivation = InitialGlobalConfig.TEAM_MOTIVATION_RULE;

        int level = 0;
        if(member.getTeamInvest()==null){
            return level;
        }
        for(int i=teamMotivation.size(); i>0; i--){
            TeamIncentiveVO incentiveVO = teamMotivation.get(i);
            if(incentiveVO.getTeamAppraisal().compareTo(member.getTeamInvest())<=0){
                level = i;
                break;
            }
        }
        return level;
    }

    private void updateLevel(TMembers member){
        // 如果是后台调整的等级,调低,则会员等级可以通过重新计算升高
        // 调高,则重新计算不能降低
        // 但如果是邀请关系调整导致的不满足,则允许调低
    }

    // 重新计算一条分支上的会员数据(只需要计算path上的会员数据,因为下级会员不会变动,整体迁移)
    // 随着邀请关系的变更,所有相关的业绩,收益,奖励等都需要跟着变动
    // 1,分支只计算一次,且取最大等级的各级别下属会员数
    // 注1:计算分支最高等级的分支数变动情况时,只有变动的那颗子树才会对新旧父级产生影响
    // 注2:分支的最高等级大于父级会员等级时,才会对父级的父级的相应等级的分支数产生影响
    // 2,重新计算团队投入,个人投入不会变动
    private void resetPathMemberData(TInvite oldInvite, TInvite newInvite, BigDecimal teamInvest,
                                     Integer oldMemberMaxLevel, Integer newMemberMaxLevel){
        Long currentInviteeId = oldInvite.getInviteeId();
        Long oldInviterId = oldInvite.getInviterId();
        String oldParentPath = oldInvite.getPath();
        Long newInviterId = newInvite.getInviterId();
        String newParentPath = newInvite.getPath();

        List<TMembers> updateParentMember = new ArrayList<>();

        List<Long> oldParentIds = path2ParentIdList(oldParentPath);
        if(!CollectionUtils.isEmpty(oldParentIds)) {
            List<TMembers> oldParentMemberList = tMemberMapper.selectBatchIds(oldParentIds);
            if(!CollectionUtils.isEmpty(oldParentMemberList)) {
                Map<Long, TMembers> oldParentMemberMap = oldParentMemberList.stream().collect(Collectors.toMap(TMembers::getCustomerId, Function.identity()));
                // 按顺序从下往上取父级id,第一个父级id就是第一代父级(距离团队最近的一个父级)
                // 变动分支的最高等级
                Integer movedBranchMaxLevel = oldMemberMaxLevel;
                // 子会员级别,变动分支的直接旧父级不增加,只减少
                Integer sonMemberLevel = -1;
                for(Long id : oldParentIds){
                    TMembers current = oldParentMemberMap.get(id);
                    Integer currentMemberLevel = current.getMemberLevel();
                    // 旧的父级会员需要扣减团队投入
                    BigDecimal currentTeamInvest = current.getTeamInvest().subtract(teamInvest);
                    if(currentTeamInvest.compareTo(BigDecimal.ZERO)<0){
                        currentTeamInvest = BigDecimal.ZERO;
                    }
                    TMembers updateMember = TMembers.builder()
                            .customerId(id)
                            .teamInvest(currentTeamInvest)
                            .build();
                    // 变动分支最高等级大于子会员等级时,变动分支最高等级的分支数要减1,子会员等级分支要加1
                    if(movedBranchMaxLevel>sonMemberLevel) {
                        substractOne(updateMember, current, movedBranchMaxLevel);
                        // 变动分支的直接旧父级不增加子会员的等级分支数
                        if(sonMemberLevel>=0) {
                            addOne(updateMember, current, sonMemberLevel);
                        }
                    }
                    sonMemberLevel = currentMemberLevel;
                    updateParentMember.add(updateMember);
                }
            }
        }
        // 新的父级会员需要增加团队投入
        List<Long> newParentIds = path2ParentIdList(newParentPath);
        if(!CollectionUtils.isEmpty(oldParentIds)) {
            List<TMembers> newParentMemberList = tMemberMapper.selectBatchIds(newParentIds);
            if(!CollectionUtils.isEmpty(newParentMemberList)) {
                Map<Long, TMembers> newParentMemberMap = newParentMemberList.stream().collect(Collectors.toMap(TMembers::getCustomerId, Function.identity()));
                // 按顺序从下往上取父级id,第一个父级id就是第一代父级(距离团队最近的一个父级)
                // 变动分支的最高等级
                Integer movedBranchMaxLevel = newMemberMaxLevel;
                // 子会员级别,变动分支的直接新父级不减少,只增加
                Integer sonMemberLevel = -1;
                for(Long id : oldParentIds){
                    TMembers current = newParentMemberMap.get(id);
                    Integer currentMemberLevel = current.getMemberLevel();
                    // 新的父级会员需要增加团队投入
                    BigDecimal currentTeamInvest = current.getTeamInvest().add(teamInvest);
                    TMembers updateMember = TMembers.builder()
                            .customerId(id)
                            .teamInvest(currentTeamInvest)
                            .build();
                    // 变动分支最高等级大于子会员等级时,变动分支最高等级的分支数要加1,子会员等级分支要减1
                    if(movedBranchMaxLevel>sonMemberLevel) {
                        addOne(updateMember, current, movedBranchMaxLevel);
                        // 变动分支的直接新父级不减少子会员的等级分支数
                        if(sonMemberLevel>=0) {
                            substractOne(updateMember, current, sonMemberLevel);
                        }
                    }
                    sonMemberLevel = currentMemberLevel;
                    updateParentMember.add(updateMember);
                }
            }
        }

        if(CollectionUtils.isEmpty(updateParentMember)){
            itMemberService.updateBatchById(updateParentMember);
        }
    }

    private List<Long> path2ParentIdList(String parentPath){
        String[] parentIdArr = parentPath.split(",");
        List<Long> parentIdList = new LinkedList<>();
        for(int i=0; i<parentIdArr.length; i++){
            parentIdList.add(Long.valueOf(parentIdArr[i]));
        }
        return parentIdList;
    }


    private void adjustMemberLevel(int newLevel, TMembers member){
        Long customerId = member.getCustomerId();
        Integer oldLevel = member.getMemberLevel();
        TMembers updateMember = TMembers.builder()
                .memberLevel(newLevel)
                .customerId(customerId)
                .build();
        // 如果待遇等级小于新等级,则同步修改待遇等级
        if(member.getEnjoyLevel()<newLevel){
            updateMember.setEnjoyLevel(newLevel);
        }
        tMemberMapper.updateById(updateMember);

        // 如果有邀请人, 需要调整邀请人的当前客户所在分支的相关数据
        // 需求:
        // 计算升级需求时,每个分支只计算一次,取最高等级
        // 计算奖金时,按日收益的百分比计算
        LambdaQueryWrapper<TInvite> inviteQuery = new LambdaQueryWrapper<>();
        inviteQuery.eq(TInvite::getInviteeId, customerId);
        TInvite inviteRel = tInviteMapper.selectOne(inviteQuery);
        if(inviteRel!=null){
            Long inviterId = inviteRel.getInviterId();
            TCustomers customer = tCustomerMapper.selectById(inviterId);
            if(customer==null){
                log.warn("邀请人[{}]不存在", inviterId);
                return;
            }
            TMembers parent = tMemberMapper.selectById(inviterId);
            if(parent==null){
                log.warn("邀请人[{}]不存在", inviterId);
                return;
            }

            // 当前客户的分支
            MemberVO branchMaxMember = branchMaxLevelMember(customerId);
            int maxLevel = 0;
            if(branchMaxMember!=null){
                maxLevel = branchMaxMember.getMemberLevel();
                log.info("[{}] branchMaxLevel: {}", customerId, maxLevel);
            }

            // 如果当前新的级别比团队最高级别高,则修改父级对应分支的推荐人数
            if(newLevel>maxLevel) {
                TMembers updateParent = TMembers.builder()
                        .customerId(inviterId)
                        .build();
                updateCount(parent, updateParent, oldLevel, oldLevel - newLevel);
                updateCount(parent, updateParent, newLevel, newLevel - oldLevel);
                tMemberMapper.updateById(updateParent);
            }
        }
    }

    public void updateCount(TMembers member, TMembers update, Integer targetLevel, Integer added){
        switch (targetLevel){
            case 0:
                update.setV0Count(member.getV0Count()+added);
                break;
            case 1:
                update.setV1Count(member.getV1Count()+added);
                break;
            case 2:
                update.setV2Count(member.getV2Count()+added);
                break;
            case 3:
                update.setV3Count(member.getV3Count()+added);
                break;
            case 4:
                update.setV4Count(member.getV4Count()+added);
                break;
            case 5:
                update.setV5Count(member.getV5Count()+added);
                break;
            default:
                break;
        }
    }

    private void substractOne(TMembers update, TMembers ori, Integer memberLevel){
        switch (memberLevel){
            case 0:
                update.setV0Count(ori.getV0Count()-1);
                break;
            case 1:
                update.setV1Count(ori.getV1Count()-1);
                break;
            case 2:
                update.setV2Count(ori.getV2Count()-1);
                break;
            case 3:
                update.setV3Count(ori.getV3Count()-1);
                break;
            case 4:
                update.setV4Count(ori.getV4Count()-1);
                break;
            case 5:
                update.setV5Count(ori.getV5Count()-1);
                break;
            case 6:
                update.setV6Count(ori.getV6Count()-1);
                break;
            default:
                break;
        }
    }

    private void addOne(TMembers update, TMembers ori, Integer memberLevel){
        switch (memberLevel){
            case 0:
                update.setV0Count(ori.getV0Count()+1);
                break;
            case 1:
                update.setV1Count(ori.getV1Count()+1);
                break;
            case 2:
                update.setV2Count(ori.getV2Count()+1);
                break;
            case 3:
                update.setV3Count(ori.getV3Count()+1);
                break;
            case 4:
                update.setV4Count(ori.getV4Count()+1);
                break;
            case 5:
                update.setV5Count(ori.getV5Count()+1);
                break;
            case 6:
                update.setV6Count(ori.getV6Count()+1);
                break;
            default:
                break;
        }
    }

    public MemberVO branchMaxLevelMember(Long customerId) {
        LambdaQueryWrapper<TInvite> branchQuery = new LambdaQueryWrapper<>();
        branchQuery.like(TInvite::getPath, customerId);
        List<TInvite> branchList = tInviteMapper.selectList(branchQuery);
        if(CollectionUtils.isEmpty(branchList)){
            return null;
        }
        List<Long> branchCustIdList = branchList.stream().map(TInvite::getInviteeId).toList();
        MemberVO memberVO = tMemberMapper.maxLevelAndMinPath(branchCustIdList);
        return memberVO;
    }
}
